package cn.edu.dutir.indri;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import lemurproject.indri.indri;

import cn.edu.dutir.utility.Constants;

import com.aliasi.util.Counter;
import com.aliasi.util.ObjectToCounterMap;

public class QueryCounter {

	private ObjectToCounterMap<String> mQueryMap;
	public List<String> mIllegalQueryNumber;
	public List<String> mIllegalQueryMsg;

	private static String DEFAULT_CHASSET = "gbk";
	private static int DEFAULT_RETURN_NUMBER = 1000;

	public QueryCounter() {
		mQueryMap = new ObjectToCounterMap<String>();
		mIllegalQueryNumber = new ArrayList<String>();
		mIllegalQueryMsg = new ArrayList<String>();
	}

	public void stat(File inFile) {
		stat(inFile, DEFAULT_CHASSET);
	}

	public void stat(File file, String charset) {
		if (file.isDirectory()) {
			statDir(file, charset);
		} else {
			statOrdinalFile(file, charset);
		}
	}

	public Set<String> querySet() {
		return mQueryMap.keySet();
	}
	
	public void statDir(File dir, String charset) {
		File files[] = dir.listFiles();
		for (File file : files) {
			stat(file, charset);
		}
	}

	public void statOrdinalFile(File inFile, String charset) {
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader(
					new FileInputStream(inFile), charset));
			String text = null;
			int lineNumber = 0;
			while ((text = reader.readLine()) != null) {
				lineNumber++;
				if(text.startsWith("UtilityThread")){
					continue;
				}
				if (text.startsWith("#")) {
					int endIndex = text.indexOf(":");
					int beginIndex = text.indexOf("# EXCEPTION in query ");
					mIllegalQueryNumber.add(text
							.substring(beginIndex, endIndex));
					String tmp = reader.readLine();
					mIllegalQueryMsg.add(text + Constants.NEWLINE + tmp);
					continue;
				}
				String fields[] = text.split(" ");
				if (fields == null || fields.length != 6) {
					String msg = "Invald format at line " + lineNumber
							+ " with " + text;
//					throw new IllegalArgumentException(msg);
					System.out.println(inFile.getAbsolutePath() + ": at line "
							+ lineNumber + " with text =" + text);

				}
				mQueryMap.increment(fields[0]);
			}
			reader.close();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	

	public void transformDir(String srcDir, String dstDir, String charset)
			throws IOException {
		BufferedReader srcbuffer;
		BufferedWriter outbuffer;
		String dataline;

		Vector inputfiles = new Vector();
		Vector outputfiles = new Vector();
		inputfiles.add(srcDir);
		outputfiles.add(dstDir);
		int i, j;
		File tmpfile, tmpout;
		String dirfiles[];
		for (i = 0; i < inputfiles.size(); i++) {
			System.out.println((String) inputfiles.get(i));
			tmpfile = new File((String) inputfiles.get(i));
			if (tmpfile.exists() == false) {
				System.out.println("ERROR: Source file "
						+ (String) inputfiles.get(i) + " does not exist./n");
				continue;
			}
			if (tmpfile.isDirectory() == true) {
				tmpout = new File((String) outputfiles.get(i));
				if (tmpout.exists() == false) {
					tmpout.mkdir();
				}

				dirfiles = tmpfile.list();
				if (dirfiles != null) {
					for (j = 0; j < dirfiles.length; j++) {
						inputfiles.add((String) inputfiles.get(i)
								+ File.separator + dirfiles[j]);
						outputfiles.add((String) outputfiles.get(i)
								+ File.separator + dirfiles[j]);

					}
				}
				continue;
			}

			System.err.println("Converting " + inputfiles.get(i) + " to "
					+ outputfiles.get(i));
			try {
				File inFile = new File((String) inputfiles.get(i));
				File outFile = new File((String) outputfiles.get(i));
				transformTWOrdinalFile(inFile, outFile, charset, false);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}
	

	public int mTotalRecord = 0;
	public void transform(File file, File outFile) {
		transform(file, outFile, DEFAULT_CHASSET, false);
	}

	public void transform(File file, File outFile, String charset) {
		transform(file, outFile, charset, false);
	}

	public void transform(File file, File outFile, boolean append) {
		transform(file, outFile, DEFAULT_CHASSET, append);
	}

	public void transform(File file, File outFile, String charset,
			boolean append) {
		if (file.isDirectory()) {
			File files[] = file.listFiles();
			for (File in : files) {
				transform(in, outFile, charset, append);
			}
		} else {
			transformOrdinalFile(file, outFile, charset, append);
		}
	}

	public void transformOrdinalFile(File inFile, File outFile) {
		transformOrdinalFile(inFile, outFile, DEFAULT_CHASSET, true);
	}

	public void transformOrdinalFile(File inFile, File outFile, boolean append) {
		transformOrdinalFile(inFile, outFile, DEFAULT_CHASSET, append);
	}

	public void transformOrdinalFile(File inFile, File outFile, String charset) {
		transformOrdinalFile(inFile, outFile, charset, false);
	}

	public void transformOrdinalFile(File inFile, File outFile, String charset,
			boolean append) {
		BufferedReader reader = null;
		BufferedWriter writer = null;
		try {
			reader = new BufferedReader(new InputStreamReader(
					new FileInputStream(inFile), charset));
			writer = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(outFile, append), charset));
			String text = null;
			int lineNumber = 0;
			while ((text = reader.readLine()) != null) {
				lineNumber++;
				if (text.startsWith("#")) {
					text = reader.readLine();
					continue;
				}
				String fields[] = text.split(" ");
				if (fields == null || fields.length != 6) {
					System.out.println(inFile.getAbsolutePath() + ": at line "
							+ lineNumber + " with text =" + text);
					continue;
				}
				Counter counter = mQueryMap.get(fields[0]);
				if (counter == null || counter.intValue() < DEFAULT_RETURN_NUMBER) {
					mQueryMap.increment(fields[0]);
					writer.write(text);
					writer.newLine();
					mTotalRecord++;
				}else{
//					System.out.println("exceed 1000 records");
				}
			}
			reader.close();
			writer.flush();
			writer.close();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void transformTWOrdinalFile(File inFile, File outFile, String charset,
			boolean append) {
		BufferedReader reader = null;
		BufferedWriter writer = null;
		try {
			reader = new BufferedReader(new InputStreamReader(
					new FileInputStream(inFile), charset));
			writer = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(outFile, append), charset));
			String text = null;
			int lineNumber = 0;
			while ((text = reader.readLine()) != null) {
				lineNumber++;
				if (text.startsWith("#")) {
					text = reader.readLine();
					continue;
				}
				String fields[] = text.split("\t");
				if (fields == null || fields.length != 4) {
					System.out.println(inFile.getAbsolutePath() + ": at line "
							+ lineNumber + " with text =" + text);
					continue;
				}
				Counter counter = mQueryMap.get(fields[0]);
				if (counter == null || counter.intValue() < 500) {
					mQueryMap.increment(fields[0]);
					writer.write(text);
					writer.newLine();
					mTotalRecord++;
				}else{
//					System.out.println("exceed 1000 records");
				}
			}
			reader.close();
			writer.flush();
			writer.close();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public int size(String queryNumber) {
		Counter counter = mQueryMap.get(queryNumber);
		return (counter != null) ? counter.intValue() : 0;
	}
	
	public int size() {
		return mQueryMap != null ? mQueryMap.size() : 0;
	}

	public void printPartialQuery() {
		Iterator<Map.Entry<String, Counter>> iter = mQueryMap.entrySet()
				.iterator();
		int number = 0;
		System.out.println("Partial querys :");
		while (iter.hasNext()) {
			Map.Entry<String, Counter> entry = iter.next();
			int value = entry.getValue().intValue();
			if (value != DEFAULT_RETURN_NUMBER) {
				System.out.println(entry.getKey() + ":" + value);
				number++;
			}
		}
		System.out.println("Partial query size : " + number);
	}

	public void printIllegalMsg() {
		System.out.println("Illegal querys :");
		Set<String> querySet = mQueryMap.keySet();
		for (int i = 0; i < mIllegalQueryNumber.size(); i++) {
			if (querySet.contains(mIllegalQueryNumber.get(i))) {
				System.out.println(mIllegalQueryNumber.get(i));
				System.out.println(mIllegalQueryMsg.get(i));
			}
		}
	}
	
	
	public void readQueryFile(Set<String> querySet, File inFile){
		XMLIndriQuery indriQuery = new XMLIndriQuery();
	}
	
	
	public static void main(String args[]) throws IOException {
		File in = new File("D:/Topic/runQuery/");
		File outFile = new File("d:/Topic/correct");
		
		in = new File("D:/Topic/final/sewm2009_retrieval_run1");
		outFile = new File("D:/Topic/final/sewm2009_retrieval_run1_top500");
		QueryCounter counter = new QueryCounter();
		// counter.stat(in);
		// System.out.println("Total query number :" + counter.size());
		// System.out.println("Error query number : "
		// + counter.mIllegalQueryNumber.size());
		// counter.printIllegalMsg();
		// counter.printPartialQuery();
		counter.transformDir(in.getAbsolutePath(), outFile.getAbsolutePath(),
				"gbk");
	}
}
